home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
COMMUNIC
/
1572A.ZIP
/
KMT_IBM3.ZIP
/
MSYIBM.ASM
< prev
Wrap
Assembly Source File
|
1989-07-11
|
120KB
|
2,387 lines
; File MSYIBM.ASM
; edit history:
; Last edit 21 Jan 1989
; 21 Jan 1989 be more tolerate of propriatary video modes above 18 when
; determining screen segment, Tnx to Terry Kennedy. Add check for IBM
; 85xx monitors on Video 7 boards, no 132 columns if it is the monitor.
; Retain 43 rows on Video 7 boards.
; 30 Nov 1988 Add SET TERM CLEAR screen clearing support.
; 28 Nov 1988 Accomodate Tseng Labs UltraPAK mono/Herc board w/132 cols.
; 132 column mode is 18h. Requires Tseng's BIGSCR.COM (use BIGSCR /R:25
; to enable 132x25 feature). Thanks to Tseng Labs for technical support.
; 21 Nov 1988 Version 2.32
; 14 Nov 1988 Write a space during lclini to obtain default screen colors.
; 12 Nov 1988 Add procs vtrmac and vtsmac to allow exit from Connect mode and
; invokation of macros TERMINALR and TERMINALS by reception of escape seqs
; in file mszibm.asm or by keyboard verbs.
; 7 Oct 1988 Reverse left/right arrow key codes when writing right to left.
; 24 Sept 1988 Make output to printer be buffered and flow controlled.
; 1 July 1988 Version 2.31
; 19 June 1988 Add Everex EVGA support, from Terry Kennedy.
; 10 June 1988 Add oldsp and procedure endcon to exit Connect mode if output
; fails, mostly for networking (but we don't know that here).
; 23 May 1988 Add Everex EV-659 ega board test from Alex Zliu. Fixed incorrect
; screen width assumption at startup.
; 29 March 1988 Include flag ttyact to group string bytes into one net packet,
; thanks to Paul Fox of AT&T.
; 23 March 1988 Add "fairness" word to let serial port deliver max chars
; between kbd reads, for connect mode only. [jrd]
; 10 Feb 1988 Revise getcirc and vtscrX routines to do proper scrolling with
; MS Window 1.0x/2.0x [jrd].
; 9 Feb 1988 Mode line again. Make flags.modflg 0 for off, 1 for on and owned
; by Kermit, and 2 for on and owned by remote host (toggling suppressed).
; 25 Jan 1988 Add global byte SCROLL, set in msz, to control emulator screen
; scrolling for higher speeds. [jrd]
; 5 Jan 1988 Restore cursor codes broken by Tek code additions. [jrd]
; 1 Jan 1988 version 2.30
public term, lclyini ; entry points
public prtbout, prtnout, csrtype, scrmod, scrseg, scrsync
public scroff, scron, atsclr, vtscru, vtscrd, scrloc, trnmod, telmsy
public chgdsp, vtroll, crt_lins, crt_cols, getflgs, tv_mode, vtclear
; action verb procedures for keyboard translator
public uparrw, dnarrw, rtarr, lfarr, pf1, pf2, pf3, pf4
public kp0, kp1, kp2, kp3, kp4, kp5, kp6, kp7, kp8, kp9
public kpminus, kpcoma, kpenter, kpdot, chrout, cstatus, cquit
public cquery, dmpscn, vtans52, vtinit, dnwpg, upwpg, endwnd, homwnd
public upone, dnone, trnprs, dumpscr, modlin, modwrt, snull
public klogon, klogof, cdos, chang, khold, vtrmac, vtsmac
public vtemu, crt_mode, scbattr, refresh, low_rgt ; data
public savescr, restscr, pntchr, pntchk, pntflsh ; code
include mssdef.h
; some definitions
; hardware
crt_status equ 3dah ; CGA crt status port
disp_enb equ 8 ; CGA display enable bit
crtmset equ 3D8H ; CGA CRT mode set port
screen equ 10h ; Bios screen interrupt
biostty equ 0eh ; Bios screen tty write mode
modfrm struc ; format of mode (status) line
db 'Esc-chr: ' ; do not write in last column
m_echr db 2 dup (?)
db ' help: '
m_hlp db 2 dup (?)
db '? port:'
m_prt db 1 dup (?)
db ' speed:'
m_baud db 5 dup (?)
db ' parity:'
m_par db 4 dup (?)
db ' echo:'
m_echo db 3 dup (?)
m_term db 13 dup (' ') ; 13 bytes for term type
m_prn db 3 dup (' ') ; show PRN when printer is on
modfrm ends
datas segment public 'datas'
extrn flags:byte, mar_top:byte, mar_bot:byte, portval:word
extrn filtst:byte, dmpname:byte, kbdflg:byte, rxtable:byte
extrn anspflg:byte, tekflg:byte, scroll:byte, ttyact:byte
extrn holdscr:byte, taklev:byte, takadr:word, mcctab:byte
; stuff for screen routines
yflags db 0 ; status flags
flags1 db 0 ; internal flags (but used in mszibm)
prtscr equ 1 ; print screen pressed
inited equ 08h ; been here before
vtinited db 0 ; flag for emulator having been inited
vtclear db 0 ; nonzero to clear emulator screen
cursor dw 0
esc_ch db 0
parmsk db 0 ; 8/7 bit parity mask, for reception
argadr dw ? ; address of arg blk
vid7id db 'VEGA BIOS Code, ' ; Video 7 Vega version string subset
vid7len equ $-vid7id ; length of string
vid7id2 db 'Video Seven BIOS Code, ' ; Video 7 VGA board
vid7len2 equ $-vid7id2
atiwid db 'ATI EGA Wonder Bios,' ; ATI EGA wonder version string subset
atilen equ $-atiwid ; length of string, inc terminator
tsngid db 'Tseng' ; Tseng Labs EVA (& Orchid Designer)
tsnglen equ $-tsngid
evrxid db 'Everex' ; Everex Micro Enhancer Deluxe EGA
evrxlen equ $-evrxid
evgid db 'VGA EV673' ; Everex EVGA EV-673
evglen equ $-evgid
ega_mode db 0 ; non-zero if IBM EGA is in use
tvhere equ 0feh ; Topview active query
tvsynch equ 0ffh ; Topview resynch request
tv_segs dw ? ; Topview virtual screen, segment
tv_sego dw ? ; and offset
tv_mode db 0 ; flag, 0 = no Topview
savadr dw 2 dup (?) ; offset then segment of saved screen
savflg dw 0 ; low_rgt at time of screen save
; The following are used to turn the display back on (after scrolling etc.)
msets db 2CH,28H,2DH,29H,2AH,2EH,1EH,29H
vtemu emulst <> ; emulator flags
ansflgs db 0 ; ANSI flags
trmtyp db 0 ; most recent terminal type
mtty db ' TTY ' ; no terminal type (mode line)
fairness dw 0
lincur dw ? ; cursor type save area
scbattr db ? ; Screen background attribute
oldattr db ? ; screen attributes at init time
curattr db ? ; current attribute
oldsp dw 0 ; offset to longjmp to for i/o failure
temp dw ? ; scratch storage
modtemp db 0 ; temp to hold Kermit modeline status
captrtn dw ? ; routine to call for captured output
dmphand dw -1 ; screen dump file handle
dumplen equ 132
dumpbuf db dumplen dup (?), cr, lf ; 134 byte dump work buffer
dumpsep db FF,cr,lf ; screen image separators
dmperr db ' Cannot open file to save screen to disk $'
crlf db cr,lf,'$'
flowon db 0 ; flow control chars xon
flowoff db 0 ; and xoff (or both null if none)
pntmsg db 'Printer not ready, printing request skipped.'
pntmsgl equ $-pntmsg ; length of pntmsg
pntptr dw dumpbuf ; pointer to next free byte in buffer
; some static data for mode line
modbuf modfrm <> ; mode line buffer
unkbaud db 'unkwn' ; must be 5 chars
baudn db ' 45.5',' 50 ',' 75 ',' 110 ','134.5',' 150 ',' 300 ',' 600 '
db ' 1200',' 1800',' 2000',' 2400',' 4800',' 9600','19200','38400'
db '57.6K','115 K'
baudnsiz equ 18 ; # of baud rates known (tbl size / 4)
parnams db 'even','mark','none','odd ','spc '
lclmsg db 'loc'
remmsg db 'rem'
portno db ?
; storage for multi-window stuff
swidth equ 80 ; max screen width
slen equ 24 ; and length of text
npages equ 10 ; # of pages of scrolling on each side
crt_norm db ? ; video mode for normal screen
crt_mode db ? ; video mode (typ 3, must be text)
crt_cols db ? ; number of screen columns (typ 80)
crt_lins db 24 ; number of screen rows - 1 (typ 24)
low_rgt dw ? ; lower right corner of text window
; high = row address (typ 23)
; low = column address (typ 79)
inipara dw ? ; initial paragraphs of scroll memory
scrsav dw ? ; segment address of save area
refresh db 0 ; screen refresh (0=wait for retrace)
vtroll db 0 ; auto roll back allowed (0 = no)
; circular buffer for screen roll back.
cbuf struc
pp dw ? ; place ptr in buffer
bend dw ? ; end of buffer
orig dw ? ; buffer origin
lcnt dw 0 ; # of lines in buffer
lmax dw ? ; max lines of buffer
cbuf ends
twnd cbuf <> ; top screen spill-buffer struct
bwnd cbuf <> ; bottom screen spill buffer struct
vtrname db 'TERMINALR' ; a macro name, must be Upper Case
vtrlen equ $-vtrname
vtsname db 'TERMINALS' ; a macro name, must be Upper Case
vtslen equ $-vtsname
vtmacname dw vtrname ; pointer to selected macro name
vtmaclen db vtrlen
datas ends
code segment public 'code'
extrn beep:near, prtchr:near, outchr:near, sbrk:near, pcwait:near
extrn isfile:near, strlen:near, strcpy:near ; in mssfil
extrn anstty:near,ansini:near,ansrei:near ; in mszibm
extrn anstat:near,anskbi:near,ansdsl:near ; in mszibm
extrn ans52t:near, vsinit:near ; in mszibm
extrn msuinit:near, keybd:near ; in msuibm
extrn tekini:near,tekcls:near,tekemu:near,tekend:near ;in msgibm
extrn tekrint:near
assume cs:code, ds:datas, es:datas
; do initialization local to this module
; Dynamically allocates 4000 bytes for screen save/restore buffer plus
; 320 to 38400 bytes for screen scroll back buffers. Tries to leave space
; for Command.com before enlarging buffers. [jrd]
lclyini proc near
call msuinit ; initialize keyboard module msuxxx
mov ax,swidth*(slen+1)*2 ; (80 char + 80 attr) * 25 lines
call sbrk ; memory allocation routine (mssker)
;if we get here them we have the lines
mov scrsav,ax ; memory segment for save screens
; screen roll back buffers
mov bx,0ffffh ; ask for all of memory, to get size
mov ah,alloc ; allocate all of memory (must fail)
int dos ; bx has # free paragraphs
mov ax,bx ; ax has copy of number free paragraphs
sub ax,24000D/16 ; space for Command.com copy #2
jbe lclyin1 ; be = not enough for it. [ebb]
cmp ax,(swidth*slen+15)/16 ; minimum roll back space left over?
jbe lclyin1 ; be = not even that much
cmp ax,(swidth*slen*npages+7)/8 ; paragraphs wanted for roll back
jbe lclyin2 ; be = enough but not more than needed
mov ax,(swidth*slen*npages+7)/8 ; limit to our actual needs
jmp short lclyin2 ; ask for all we really want
lclyin1:mov ax,(4*swidth+15)/16 ; use minimum needed paragraphs
lclyin2:mov inipara,ax ; save for later resizing of buffers
mov cl,4 ; convert paragraphs to bytes
shl ax,cl ; for sbrk
call sbrk ; ask for that many bytes
;if we get here them we have the space
mov bwnd.orig,ax ; memory segment, bottom window area
mov twnd.orig,ax ; top. same place for both buffers!
call scrseg ; test running in an Environment
call scrmod ; read video state, get crt_mode
mov ax,low_rgt ; lower right corner of screen
mov al,crt_mode
mov crt_norm,al ; save as normal mode
mov savflg,ax
mov ah,conout ; output a space to set background
mov dl,' ' ; and foreground screen colors
int dos
mov ah,3 ; get current cursor position into dx
mov bh,0
int screen
dec dl ; backup to the space
mov ah,2 ; set cursor
int screen
mov ah,8 ; read current attributes
xor bh,bh ; page 0
int screen
mov scbattr,ah ; save video attributes
mov oldattr,ah ; and here too
mov ax,inipara ; # paragraphs allocated by DOS
mov cl,3 ; 2**3 = 8
shl ax,cl ; paragraphs to words (char + attrib)
xor dx,dx ; clear extended size
mov ch,0
mov cl,byte ptr low_rgt
inc cl ; number of chars per line in buffer
div cx ; ax = number of lines in buffer
mov bwnd.lmax,ax ; max lines per buffer (quotient)
mov twnd.lmax,ax ; max lines per buffer
add cx,cx ; count char and attribute per item
xor dx,dx ; clear extended numerator
mul cx ; ax = effective # bytes per buffer
dec ax ; adjust for counting from zero
mov bwnd.bend,ax ; offset of last byte in buffer
mov twnd.bend,ax ; offset of last byte in buffer
mov bwnd.pp,0 ; offset of first byte in buffer
mov twnd.pp,0 ; offset of first byte in buffer
mov bwnd.lcnt,0 ; number of lines occupied in buffer
mov twnd.lcnt,0 ; number of lines occupied in buffer
call vsinit ; init terminal emulator module MSZ
mov ega_mode,0 ; assume no EGA
mov ax,1200H ; EGA: Bios alternate select
mov bl,10H ; Ask for EGA info
mov bh,0ffH ; Bad info, for testing
mov cl,0fH ; Reserved switch settings
int screen ; EGA, are you there?
cmp cl,0cH ; Test reserved switch settings
jge lclyin3 ; ge = no EGA in use
push es
mov ax,40h ; check Bios 40:87h for ega being
mov es,ax ; the active display adapter
test byte ptr es:[87h],8 ; is ega active?
pop es
jnz lclyin3 ; nz = no
mov ega_mode,1 ; yes, set flag to say so
mov crt_norm,3 ; assume color monitor is attached
cmp bh,0 ; is color mode in effect?
je lclyin3 ; e = yes
mov crt_norm,7 ; else use mode 7 for mono
lclyin3:ret
lclyini endp
scrini proc near ; init screen stuff
call scrseg ; update screen segment tv_seg(s/o)
call scrmod ; get screen mode, low_rgt
mov ah,3 ; get cursor position and type
xor bh,bh ; page 0
int screen
mov lincur,cx ; save cursor type (scan line #'s)
mov ax,low_rgt ; present screen text size
cmp ax,savflg ; vs size of saved screen
jne scrin1 ; ne = different, initialize
jmp scrin3 ; same, skip initialization
; Re-initialize screen buffers
scrin1: mov ax,inipara ; paragraphs allotted to roll back
mov cl,3 ; 2**3 = 8
shl ax,cl ; paragraphs to words (char + attrib)
xor dx,dx ; clear extended size
mov cl,byte ptr low_rgt ; number of chars per line in buffer
inc cl ; chars per line
xor ch,ch ; clear high byte
div cx ; ax = number of lines in buffer
mov bwnd.lmax,ax ; max lines per buffer (quotient)
mov twnd.lmax,ax ; max lines per buffer
add cx,cx ; count char and attribute per item
xor dx,dx ; clear extended numerator
mul cx ; ax = effective # bytes per buffer
dec ax ; adjust for counting from zero
mov bwnd.bend,ax ; offset of last byte in buffer
mov twnd.bend,ax ; offset of last byte in buffer
mov bwnd.pp,0 ; offset of first byte in buffer
mov twnd.pp,0 ; offset of first byte in buffer
mov bwnd.lcnt,0 ; number of lines occupied in buffer
mov twnd.lcnt,0 ; number of lines occupied in buffer
mov ega_mode,0 ; assume no EGA
mov ax,1200H ; EGA: Bios alternate select
mov bl,10H ; Ask for EGA info
mov bh,0ffH ; Bad info, for testing
mov cl,0fH ; Reserved switch settings
int screen ; EGA, are you there?
cmp cl,0cH ; Test reserved switch settings
jge scrin2 ; ge = no EGA in use
push es
mov ax,40h ; check Bios 40:87h for ega being
mov es,ax ; the active display adapter
test byte ptr es:[87h],8 ; is ega active?
pop es
jnz scrin2 ; nz = no
mov ega_mode,1 ; yes, set flag to say so
mov crt_norm,3 ; assume color monitor is attached
cmp bh,0 ; is color mode in effect?
je scrin2 ; e = yes
mov crt_norm,7 ; else use mode 7 for mono
scrin2: mov ah,oldattr ; get init time attributes
mov curattr,ah ; and set nice screen attribute
mov scbattr,ah
mov cursor,0 ; cursor to upper left corner
cmp flags.vtflg,0 ; terminal type of None?
ja scrin3 ; a = no, emulating
mov dh,byte ptr low_rgt+1
inc dh ; bottom
mov dl,0 ; left corner
jmp short scrin5
; Common finish code
scrin3: mov dx,cursor ; use old cursor, if any
cmp flags.vtflg,0 ; emulating?
je scrin4 ; e = no
cmp dh,byte ptr low_rgt+1 ; past logical end of screen?
jbe scrin4 ; be = no, keep going
mov dh,byte ptr low_rgt+1 ; yes, just use lower right corner
scrin4: cmp dl,byte ptr low_rgt ; maybe past right margin
jbe scrin5 ; be = no, use the way it is
mov dl,byte ptr low_rgt
scrin5: mov cursor,dx ; init cursor
mov ah,2 ; set cursor position
xor bh,bh ; page zero
int screen ; set cursor in case it moved
test flags1,inited ; have we run yet?
jz scrin7 ; z = no, so no saved screen yet
call restscr ; restore screen
scrin7: or flags1,inited ; remember we've run already
cmp flags.modflg,1 ; is mode line on and locally owned?
ja scrin10 ; a = host owned, leave intact
cmp flags.vtflg,0 ; emulating a terminal?
jne scrin8 ; ne = yes, can have mode line
or yflags,modoff ; for no emulation say toggled off
cmp trmtyp,0 ; previous terminal type = none?
jne scrin9 ; ne = no. need to clear mode line
jmp scrin10 ; yes, let 25th line be intact
scrin8: cmp flags.modflg,0 ; is mode line disabled?
je scrin9 ; e = yes, clear it
test yflags,modoff ; is mode line toggled off?
jnz scrin9 ; nz = yes, clear the line
call modlin ; turn on mode line
jmp short scrin10
scrin9: call clrmod ; ensure its off
scrin10:cmp flags.vtflg,0 ; current terminal type = None?
je scrin12 ; e = yes, nothing to init
mov al,yflags ; tell emulator we are back
cmp vtclear,0 ; screen need clearing?
jne scrin10a ; yes, do emulator reinit now
cmp vtinited,inited ; inited emulator yet?
je scrin11 ; e = yes
cmp tekflg,0 ; Tek mode still active?
jne scrin12 ; ne = yes, no re-init here
scrin10a:call vtinit ; init it now
mov vtclear,0 ; say screen is clear
jmp short scrin12
scrin11:call ansrei ; reinit the emulator
call ansflg ; and get its flags
scrin12:mov al,flags.vtflg ; current terminal type
mov trmtyp,al ; place to remember it til next time
cmp flags.vtflg,tttek ; Tek mode?
je scrin13 ; e = yes
cmp tekflg,0 ; Tek mode active within DEC stuff?
je scrin14 ; e = no
scrin13:call tekini ; reinit to get graphics screen
scrin14:ret
scrini endp
; Routine to initialize VT102/52/Heath-19 terminal emulator.
vtinit proc near
mov holdscr,0 ; clear holdscreen
cmp flags.vtflg,0 ; doing emulation?
je vtinix ; e = no
cmp tekflg,0 ; Tek mode active?
jne vtini2 ; ne = yes, do it's reinit
or vtinited,inited
call ansflg ; update ansi flags
mov bx,argadr ; Get address of argument block
mov dl,[bx].flgs
and dl,lclecho
and yflags,not lclecho
or yflags,dl
mov al,yflags ; Pass the flags
mov dl,[bx].baudb ; Baud rate code in dl
mov dh,[bx].parity ; Parity code in bits
mov cl,4 ; 0-3 of dh
shl dh,cl
or dh,07H ; Just say 7 data bits
test flags.remflg,d8bit ; eight bit display?
jz vtini1 ; z = no
inc dh ; set low four bits to value 8
vtini1: call ansini ; call startup routine in mszibm
vtinix: clc
ret
vtini2: call tekrint ; reinitialize Tek emulator
clc
ret
vtinit endp
argini proc near ; read passed arguments
mov bx,argadr ; base of argument block
mov al,[bx].flgs ; get flags
and al,capt+emheath+havtt+trnctl+lclecho+modoff+lnwrap
mov yflags,al ; mask for allowable and save
mov al,[bx].prt
mov portno,al ; update port number
mov al,[bx].rows
mov crt_lins,al ; init # of rows and cols
mov ax,[bx].captr
mov captrtn,ax ; buffer capture routine
mov al,[bx].escc
mov esc_ch,al
mov parmsk,0ffh ; parity mask, assume parity = None
cmp [bx].parity,parnon ; is parity None?
je argini1 ; e = yes, keep all 8 bits
mov parmsk,07fh ; else keep lower 7 bits
argini1:ret ; that's it
argini endp
modlin proc near ; turn on mode line
mov al,esc_ch
mov modbuf.m_echr,' ' ; first char is initial space
mov modbuf.m_hlp,' ' ; goes here too
cmp al,32 ; printable?
jnb modl1 ; yes, keep going
add al,40h ; made printable
mov modbuf.m_echr,5eh ; caret, note control char
mov modbuf.m_hlp,5eh
modl1: mov modbuf.m_echr+1,al ; fill in character
mov modbuf.m_hlp+1,al
mov bx,argadr ; get argument block
mov al,[bx].baudb ; get baud bits
mov si,offset unkbaud ; assume unknown baud
cmp al,baudnsiz ; too big?
jnb modl2 ; nb = yes, use default
mov cl,size m_baud ; each is 5 bytes long
mul cl
mov ah,0
add ax,offset baudn
mov si,ax
modl2: mov cx,size m_baud ; length of baud space
mov di,offset modbuf.m_baud
push es ; save es
push ds
pop es ; set es to datas segment
cld
rep movsb ; copy in baud rate
mov al,[bx].parity ; get parity code
shl al,1 ; each is 4 bytes long
shl al,1
mov ah,0
add ax,offset parnams ; names of parity settings
mov si,ax
mov cx,4 ; each is 4 long
mov di,offset modbuf.m_par
rep movsb
mov si,offset remmsg ; Assume remote echoing
test yflags,lclecho ; Is remote side echoing?
jz modl4 ; Yes, keep going
mov si,offset lclmsg ; Else it's local echoing.
modl4: mov cx,3 ; size of on/off
mov di,offset modbuf.m_echo
rep movsb
mov al,portno ; communications port
cmp al,' ' ; binary (non-printable)?
jae modl5 ; ae = no, ascii
add al,'0' ; convert to ascii
modl5: mov modbuf.m_prt,al ; fill in port number
mov cx,8 ; blank out terminal id field
mov si,offset mtty ; assume no terminal emulation
mov di,offset modbuf.m_term ; destination
rep movsb ; copy it in
mov modbuf.m_prn,' ' ; assume not printing the screen
mov modbuf.m_prn+1,' '
mov modbuf.m_prn+2,' '
test anspflg,prtscr ; doing a print the screen?
jz modl5a ; z = no
mov modbuf.m_prn,'P' ; yes. display PRN at end of line
mov modbuf.m_prn+1,'R'
mov modbuf.m_prn+2,'N'
modl5a: mov cx,size modfrm ; this is size of mode line
mov si,offset modbuf ; mode line image
pop es
; alternate entry to write an alternate mode line
modwrt: push cx
push si ; save mode line and size
mov ah,3 ; read cursor position
xor bx,bx ; screen page 0
int screen
mov cursor,dx ; save cursor position
call trmatt ; Get terminal attributes
and ah,77h ; omit blinking/bold attributes
mov bh,ah ; get video attribute
mov dx,low_rgt ; right most column
inc dh ; refer to status line
mov ch,dh ; bottom line [dlk]
mov cl,0 ; left col = 0 (first) [dlk]
mov ax,600h ; scroll to clear the line
int screen
mov dh,byte ptr low_rgt+1 ; refer to status line
inc dh
xor dl,dl ; left most column
mov bh,0
mov ah,2 ; set cursor position
int screen
pop si
pop cx ; restore these
cmp cl,crt_cols ; mode line longer than screen?
jbe modl6 ; le = no
mov cl,crt_cols ; else do just one line's worth
dec cx ; don't let screen scroll
modl6: cld
lodsb ; get a byte
mov ah,14 ; write to terminal
mov bh,0 ; page 0
int screen
loop modl6 ; write out entire mode line
cmp flags.vtflg,0 ; emulating?
je modl7 ; e = no
and yflags,not modoff ; update local flags (mode line on)
mov al,yflags ; Yes - update flags also
call ansdsl ; get extras from emulator
modl7: mov dx,cursor
mov ah,2
mov bh,0
int screen ; put cursor back where it belongs
ret
modlin endp
clrmod proc near ; clear mode line
call trmatt ; Get terminal screen attributes
mov bh,al ; Use screen background attribute
mov ax,600h ; blank window
mov dx,low_rgt ; right most column
inc dh ; refer to status line
mov cx,dx ; bottom line [dlk]
xor cl,cl ; left most column
int screen ; clear mode line
or yflags,modoff ; turn on flag
ret
clrmod endp
; Fetch screen attributes from emulator (if emulating). It exists mainly
; so that the reverse video will work. Returns the current mode
; line background attribute in ah, the current screen background in al,
; and the current "cursor" (foreground) attribute in bl. (Note: anstat
; returns status yflags in bh).
trmatt proc near ; Get attributes
cmp flags.vtflg,0 ; emulating?
je trmat1 ; No, just do simple stuff
mov al,yflags ; anstat expects flags byte in al
call anstat ; Fetch emulator status/attributes
ret
trmat1: mov al,scbattr ; Background attributes
mov bl,curattr ; And cursor attribute
mov ah,al ; where modlin needs them
and ah,77h ; get colors part, no blink/bold
rol ah,1 ; reverse them
rol ah,1
rol ah,1
rol ah,1
ret
trmatt endp
; Get byte yflags of terminal emulator passed in AL. Used in mode line
; handling when 25th line is used by the emulator. [jrd]
telmsy proc near
mov yflags,al ; get the updated flags
call ansflg ; and any other emulator info
ret
telmsy endp
;[IU2] This routine updates the ANSI status flags from the emulator,
; and passes the "yflags" byte to the VT100 emulator also.
ansflg proc near
push ax ; save regs
push bx
mov al,yflags
call anstat ; Get status and attributes
mov ansflgs,bh ; Save
test ansflgs,dececho ; does host want us to do local echo?
jz ansflg1 ; z = no, use working default
or yflags,lclecho ; turn on local echoing
ansflg1:pop bx
pop ax
ret
ansflg endp
getflgs proc near ; supply yflags for terminal emulators
mov al,yflags
ret
getflgs endp
term proc near ; terminal mode entry point
mov argadr,ax ; save argument ptr
call argini ; init options from arg address
call scrini ; init screen stuff
mov bx,portval ; port data structure address
mov bx,[bx].flowc ; get flow control chars (bl=xoff)
mov flowon,bh
mov flowoff,bl ; save for later
mov oldsp,sp ; remember stack for i/o failure,
; used by procedure endcon
lp: call prtchr ; char at port?
jmp short lpinp ; yes, go handle
nop ; else look at kbd
lpkbd: mov fairness,0 ; say kbd was examined
call keybd ; call keyboard translator in msu
jnc lp ; nc = no char or have processed it
jmp short quit ; carry set = quit connect mode
lpinp: and al,parmsk ; apply 8/7 bit parity mask
call outtty ; print on terminal
inc fairness ; say read port but not kbd, again
cmp fairness,100 ; this many port reads before kbd?
jb lp ; b = no, read port again
jmp short lpkbd ; yes, let user have a chance too
quit: call pntflsh ; flush printer buffer
call tekend ; cleanup Tektronix mode [bjh]
mov ah,3 ; get cursor position into dx
xor bh,bh ; page 0
int screen
mov cursor,dx ; save position
cmp flags.vtflg,0 ; terminal type of none?
ja quit1 ; a = yes
test yflags,modoff ; is modeline still toggled off?
jnz quit1 ; nz = yes
call clrmod ; clear it before storing screen
quit1: call savescr ; save screen
mov ax,0600h ; clear mode line with old attributes
mov bh,oldattr ; attributes
mov dx,low_rgt ; right most column
inc dh ; refer to status line
mov cx,dx ; bottom line [dlk]
xor cl,cl ; left most column
int screen ; clear the mode line
mov ah,oldattr ; attributes at init time
mov scbattr,ah ; background = original state
; for ega in non-standard # lines
cmp ega_mode,0 ; ega board active?
je quit2 ; e = no
cmp byte ptr low_rgt+1,23 ; is screen standard length?
je quit2 ; e = yes, so regular cursor set is ok
push es ; turn off ega cursor emulation
mov ax,40h ; byte 40:87H is ega Info byte
mov es,ax
push es:[87h] ; save info byte around call
or byte ptr es:[87h],1 ; set emulation off (low bit = 1)
mov cx,lincur ; cursor shape to set
mov ah,1 ; set the shape
int screen ; back to starting value
pop es:[87h] ; recover original Info byte
pop es ; and our work reg
jmp short quit3 ; skip regular mode cursor setting
quit2: ; for regular sized screen
mov cx,lincur ; cursor type at startup
mov ah,1
int screen ; restore cursor type
quit3: mov ah,2 ; Position cursor
mov bh,0 ; Page 0
mov dx,low_rgt ; bottom line
inc dh ; status line position
xor dl,dl ; left most column
int screen ; Do it
mov al,yflags
and al,not lclecho ; don't copy host's echo flag
mov bx,argadr
mov ah,[bx].flgs ; get user's flag settings
and ah,lclecho ; clear all but local echo bit
or [bx].flgs,al ; update flags in arg block
ret
term endp
; put the character in al to the screen
outtty proc near
cmp flags.vtflg,0 ; emulating a terminal?
jne outnoc ; ne = yes, emulator handles printing
test flags.remflg,d8bit ; keep 8 bits for displays?
jnz outnp9 ; nz = yes, 8 bits if possible
and al,7fh ; remove high bit
outnp9: cmp rxtable+256,0 ; translation turned off?
je outnp7 ; e = yes, no translation
push bx
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
pop bx
outnp7: test anspflg,prtscr ; should we be printing?
jz outnop ; no, keep going
call pntchr ; queue char for printer
jnc outnop ; nc = successful print
push ax
call beep ; else make a noise and
call trnprs ; turn off printing
pop ax
outnop: test yflags,capt ; capturing output?
jz outnoc ; no, forget this part
push ax ; save char
call captrtn ; give it captured character
pop ax ; restore character and keep going
outnoc: cmp vtroll,0 ; auto roll back allowed?
jz outnp6 ; z = no, leave screen as is
cmp tekflg,0 ; Tek mode active?
jne outnp6 ; ne = yes, skip screen rolling
cmp bwnd.lcnt,0 ; is screen rolled back? [dlk]
je outnp6 ; e = no
call endwnd ; restore screen before writing [dlk]
outnp6: cmp flags.vtflg,0 ; emulating a terminal?
jne outnop1 ; ne = yup, go do something smart
test yflags,trnctl ; debug? if so use Bios tty mode
jz outnp4 ; z = no
mov ah,biostty ; Bios tty screen write
cmp al,7fh ; Ascii Del char or greater?
jb outnp1 ; b = no
je outnp0 ; e = Del char
push ax ; save the char
mov al,7eh ; output a tilde for 8th bit
int screen
pop ax ; restore char
and al,7fh ; strip high bit
outnp0: cmp al,7fh ; is char now a DEL?
jne outnp1 ; ne = no
and al,3fH ; strip next highest bit (Del --> '?')
jmp outnp2 ; send, preceded by caret
outnp1: cmp al,' ' ; control char?
jae outnp3 ; ae = no
add al,'A'-1 ; make visible
outnp2: push ax ; save char
mov al,5eh ; caret
int screen ; display it
pop ax ; recover the non-printable char
outnp3: push ax
int screen
pop ax
ret
outnp4: cmp al,bell ; bell (Control G)?
jne outnp5 ; ne = no
jmp beep ; use short beep, avoid char loss
outnp5: mov dl,al ; write without intervention
mov ah,conout
int dos ; else let dos display char
ret
outnop1:cmp flags.vtflg,tttek ; doing Tektronix emulation?
je outnop2 ; e = yes, use Tek emulator
cmp tekflg,0 ; Tek submode active?
jne outnop2 ; ne = yes, use Tek emulator
jmp anstty ; call terminal emulator routine & ret
outnop2:jmp tekemu ; use Tek emulator and return
outtty endp
;[IU2] Here to output character to port with no echo (like escape sequences
; sent by PF keys, responses to requests from the host, etc. It is
; wrong thinking to echo these).
prtbout proc near ; Global routine now
mov ah,al ; This is where outchr expects it
call outchr
jmp endcon ; failure, end connection
nop
clc ; carry clear for success
ret
prtbout endp
;[IU2] Here to output an unsigned 8-bit number (in al) to the port without
; echoing. Used by terminal emulator escape sequence output.
prtnout proc near
mov bl,10 ; Output in base 10
jmp prtno2 ; Ensure at least a zero
prtno1: cmp al,0
jne prtno2 ; Yes - do more digits
ret ; No - return from recursive call
prtno2: mov ah,0 ; Clear previous remainder
div bl ; Divide off a digit
push ax ; Push remainder (in ah) on stack
call prtno1 ; Recur
pop ax ; Pop off a digit
add ah,'0' ; Make it ASCII
call outchr ; send to port
jmp endcon ; failure, end connection
nop
clc ; carry clear for success
ret
prtnout endp
; send the character in al out to the serial port; handle echoing.
; Can send an 8 bit char while displaying only 7 bits locally.
outprt proc near
test yflags,lclecho ; echoing?
jz outpr1 ; z = no, forget it
push ax ; save char
call outtty ; print it
pop ax ; restore
outpr1: mov ah,al ; this is where outchr expects it
call outchr ; output to the port
jmp endcon ; failure, end connection
nop
clc ; carry clear for success
ret
outprt endp
; Jump here to exit Connect mode and execute macros 'TERMINALR' (vtrmac) or
; 'TERMINALS' (vtsmac). Does nothing if macro does not exist.
; Preserves registers except ax. Returns to TELNET caller with 'C' in kbdflg.
vtrmac proc near ; RESET macro
mov ax,offset vtrname ; select macro name
mov vtmacname,ax
mov vtmaclen,vtrlen ; and its length
jmp short vtmacro ; finish in common code
vtrmac endp
vtsmac proc near ; SET macro
mov ax,offset vtsname
mov vtmacname,ax
mov vtmaclen,vtslen
jmp short vtmacro
vtsmac endp
;
; Reference Macro structure for db number of entries (mac names)
; is file table mcctab |-> db length of macroname, excl '$'
; mssset.asm each entry |-> db 'macroname','$'
; where these |-> dw offset of definition string
; are stored.
; Definition string in db length of <string with null>
; buffer macbuf db 'string with trailing null'
;
vtmacro proc near ; common code for macros vtsmac,vtrmac
push bx
push cx
push si
mov bx,offset mcctab ; table of macro names
mov cl,[bx] ; number of names in table
xor ch,ch
jcxz vtmacx ; z = empty table, do nothing
inc bx ; point to length of first name
vtmac2: mov al,[bx] ; length of this name
xor ah,ah
cmp al,vtmaclen ; length same as desired keyword?
jne vtmac3 ; ne = no, search again
mov si,bx
inc si ; point at first char of name
push cx ; save name counter
push di ; save reg
mov cl,vtmaclen ; length of name, excluding '$'
xor ch,ch
mov di,vtmacname ; point at desired macro name
push es ; save reg
push ds
pop es ; make es use datas segment
cld
repe cmpsb ; match strings
pop es ; need current si below
pop cx
pop di ; recover saved regs
je vtmac4 ; e = matched
vtmac3: add bx,ax ; step to next name, add name length
add bx,4 ; + count, dollar sign, def word ptr
loop vtmac2 ; try next name
vtmacx: pop si ; no macro, return to Connect mode
pop cx
pop bx
ret
vtmac4: cmp taklev,maxtak ; room in Take level?
jge vtmacx ; ge = no, exit with no action
inc taklev ; increment take level
add takadr,size takinfo ; make a new Take entry/macro
mov bx,takadr ; point to current macro structure
inc si ; skip dollar sign after name
mov si,[si] ; get definition address
mov [bx].takbuf,si ; address of definition string struc
mov cl,[si] ; length byte of definition
xor ch,ch
mov [bx].takcnt,cx ; number of chars in definition
inc si ; address of definition text proper
mov [bx].takptr,si ; where to read next command char
mov [bx].taktyp,0ffh ; flag as a macro
pop si
pop cx
pop bx
jmp endcon ; exit Connect mode
vtmacro endp
; Error recovery routine used when outchr reports unable to send character
; or when vtmacro requests exiting Connect mode.
; Exit Connect mode cleanly, despite layers of intermediate calls.
endcon proc near
mov kbdflg,'C' ; report 'C' to TERM's caller
mov sp,oldsp ; recover startup stack pointer
; TERM caller's return address is now
; on the top of stack. A longjmp.
jmp quit ; exit Connect mode cleanly
endcon endp
;;; Action routines (verbs) for keyboard translator KEYBD in msuibm.
; These are invoked by a jump instruction. Return carry clear for normal
; processing, return carry set for invoking Quit (kbdflg has transfer char).
uparrw: mov al,'A' ; cursor keys
jmp short comarr
dnarrw: mov al,'B'
jmp short comarr
rtarr: mov al,'C'
test vtemu.vtflgop,vswdir ; writing left to right?
jz comarr ; z = yes
mov al,'D' ; reverse sense of keys
jmp short comarr
lfarr: mov al,'D'
test vtemu.vtflgop,vswdir ; writing left to right?
jz comarr ; z = yes
mov al,'C' ; reverse sense of keys
comarr: push ax ; save final char
mov ttyact,0 ; network, group chars for packet
mov al,escape ; Output an escape
call outprt ; Output, echo permitted
cmp flags.vtflg,tttek ; Tek terminal?
je comar0 ; e = yes, use VT100 codes
cmp flags.vtflg,ttvt100 ; VT100 terminal emulation?
jne comar2 ; No, do VT52/HEATH-19 sequence
comar0: call ansflg ; Update flags all around
mov al,'[' ; Maybe this next?
test ansflgs,decckm ; Cursor key mode reset?
je comar1 ; Yes, output the "["
mov al,'O' ; No, set, use the "O"
comar1: call outprt ; Output it (echo permitted)
comar2: pop ax ; recover final char
mov ttyact,1 ; network, restore tty active flag
call outprt ; Output to port (echo permitted)
ret
pf1: mov al,'P' ; keypad function keys 1-4
jmp short compf
pf2: mov al,'Q'
jmp short compf
pf3: mov al,'R'
jmp short compf
pf4: mov al,'S'
compf: push ax ; save final char
mov ttyact,0 ; network, group chars for packet
mov al,escape ; Output an escape
call prtbout
call ansflg ; get emulator flags
test ansflgs,decanm ; ansi mode?
jz short compf1 ; z = no
mov al,'O' ; send an "O"
call prtbout ; Output it
compf1: pop ax ; Get the saved char back
mov ttyact,1 ; network, restore tty active flag
call prtbout ; Output to port
ret
kp0: mov al,'p' ; keypad numeric keys
jmp short comkp
kp1: mov al,'q'
jmp short comkp
kp2: mov al,'r'
jmp short comkp
kp3: mov al,'s'
jmp short comkp
kp4: mov al,'t'
jmp short comkp
kp5: mov al,'u'
jmp short comkp
kp6: mov al,'v'
jmp short comkp
kp7: mov al,'w'
jmp short comkp
kp8: mov al,'x'
jmp short comkp
kp9: mov al,'y'
jmp short comkp
kpminus:mov al,'m'
jmp short comkp
kpcoma: mov al,'l'
jmp short comkp
kpenter:mov al,'M'
jmp short comkp
kpdot: mov al,'n'
comkp: test ansflgs,deckpam ; keypad application mode active?
jnz comkp3 ; nz = yes, use escape sequences
sub al,40h ; deduct offset to numeric symbols
jmp comkp0 ; and send that single char
comkp3: push ax ; save final char
mov ttyact,0 ; network, group chars for packet
mov al,escape ; Output an escape
call prtbout
mov al,'O' ; Output the "O"
cmp flags.vtflg,ttvt100 ; VT100 mode?
je comkp1 ; e = yes, use "O" code
cmp flags.vtflg,tttek ; Tek terminal
je comkp1 ; e = yes, use VT100 codes
test ansflgs,decanm ; ANSI (alt application keypad) mode?
jnz comkp1 ; nz = yes, use "O"
comkp2: mov al,'?' ; else use "?" instead of "O"
comkp1: call prtbout
pop ax ; recover final char
comkp0: mov ttyact,1 ; network, restore tty active flag
call prtbout ; send it
ret
klogon proc near ; resume logging (if any)
test flags.capflg,logses ; session logging enabled?
jz klogn ; z = no, forget it
or argadr.flgs,capt ; turn on capture flag
or yflags,capt ; set local msy flag as well
call ansflg ; tell emulator
klogn: clc
ret
klogon endp
klogof proc near ; suspend logging (if any)
and argadr.flgs,not capt ; stop capturing
and yflags,not capt ; reset local msy flag as well
call ansflg ; tell emulator
klogo: clc
ret
klogof endp
snull proc near ; send a null byte
mov al,0 ; the null
jmp prtbout ; send without logging and local echo
snull endp
khold: xor holdscr,1 ; toggle Hold screen byte for msx
clc
ret
; general character out for emulator
chrout: cmp flags.vtflg,0 ; emulating?
je chrou5 ; e = no
call anskbi ; Yes, say we had keyboard input
cmp al,cr ; A CR?
jne chrou5 ; No - just output it and return
call ansflg ; Yes - update VT100 flags
test ansflgs,anslnm ; ANSI new-line mode set?
jz chrou5 ; No - just send the cr
call outprt ; Yes - output a carriage-return
mov al,lf ; Followed by a line feed
chrou5: call outprt
ret
; these commands invoke Quit
cdos: mov al,'P' ; Push to DOS
jmp short cmdcom
cstatus:mov al,'S' ; Status
jmp short cmdcom
cquit: mov al,'C' ; Exit Connect mode
jmp short cmdcom
cquery: mov al,'?' ; Help
jmp short cmdcom
chang: mov al,'H' ; Hangup, drop DTR & RTS
jmp short cmdcom
cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg
stc ; signal that Quit is needed
ret
dmpscn proc near ; dump screen to file
call savescr ; save screen to buffer
call dumpscr ; do buffer to file
clc ; do not exit Connect mode
ret
dmpscn endp
;[IU2] Routine to toggle VT100/VT52/Heath-19 modes in VT100 emulator.
vtans52 proc near
cmp flags.vtflg,0 ; emulating?
je vtans5 ; e = no
call ans52t ; Call MSZ toggle-it routine
call ansflg ; Update flags
clc ; clear c bit so don't exit Connect
vtans5: ret
vtans52 endp
; Toggle Mode Line
trnmod: cmp flags.modflg,1 ; mode line enabled and owned by us?
jne trnm2 ; ne = no, don't touch it
cmp flags.vtflg,tttek ; Tek mode?
je trnm2 ; yes
cmp tekflg,0 ; Tek submode?
jne trnm2 ; ne = yes, no mode line changes
test yflags,modoff ; mode line already off?
jnz trnm1 ; yes, go turn on
call clrmod ; no, clear mode line here
or yflags,modoff ; turn on flag
call ansflg ; Update flags all around
clc ; clear c bit so don't exit Connect
ret
trnm1: and yflags,not modoff ; Clear flag first
cmp flags.vtflg,0 ; terminal type of none?
ja trnm3
push dx ; scroll screen to save bottom line
mov ah,prstr ; for terminal type none
mov dx,offset crlf
int dos
pop dx
trnm3: call modlin ; Then turn on mode line
call ansflg ; Update flags all around
trnm2: clc
ret
trnprs: push ax ; toggle ^ PrtSc screen to printer
test anspflg,prtscr ; are we currently printing?
jnz trnpr2 ; nz = yes, its on and going off
mov ah,ioctl
mov al,7 ; get output status of printer
push bx
mov bx,4 ; file handle for system printer
int dos
pop bx
jc trnpr1 ; c = printer not ready
cmp al,0ffh ; Ready status?
je trnpr2 ; e = Ready
trnpr1: call beep ; Not Ready, complain
jmp trnpr3 ; and ignore request
trnpr2: xor anspflg,prtscr ; flip the flag
test yflags,modoff ; mode line off?
jnz trnpr3 ; nz = yes
call modlin ; else rewrite mode line
trnpr3: pop ax
clc ; return carry clear (don't quit)
ret
; Print on PRN the char in register al. On success return with C bit clear.
; On failure do procedure pntchk and return its C bit (typically C set).
; Uses buffer dumpbuf (screen dump).
pntchr proc near
push bx ; buffer the character
mov bx,pntptr ; offset of next free byte in buffer
mov [bx],al ; store the character
inc bx ; update pointer
mov pntptr,bx ; save pointer
cmp bx,offset dumpbuf+dumplen ; buffer full yet?
pop bx
jb pntchrx ; b = no, just return
jmp pntflsh ; go flush the buffer
pntchrx:clc ; clear carry bit
ret
pntchr endp
; Flush printer buffer. Return carry clear if success.
; On failure do procedure pntchk and return its C bit (typically C set).
; Uses buffer dumpbuf (screen dump).
pntflsh proc near
cmp pntptr,offset dumpbuf ; any text in buffer?
jne pntfls1 ; ne = yes
ret ; else nothing to do
pntfls1:push ax
push bx
push cx
push dx
mov bx,portval
mov bx,[bx].flowc ; get flow control chars (bl=xoff)
mov flowon,bh
mov flowoff,bl ; save for later
mov al,bl ; get flow control char
cmp al,0 ; flow control active?
je pntfls2 ; e = no, not using xoff
call prtbout ; output xoff (al), no echo
pntfls2:mov ah,write2
mov bx,4 ; file handle for DOS printer PRN
mov cx,pntptr ; next free byte in buffer
mov dx,offset dumpbuf ; start of buffer
mov pntptr,dx ; reset buffer pointer
sub cx,dx ; cx = current byte count
jcxz pntfls3 ; z = empty, do nothing
int dos ; write buffer to printer
pntfls3:pushf ; save carry status bit
mov al,flowon
cmp al,0 ; flow control active?
je pntfls4 ; e = no, not using xon
call prtbout ; output xon (al), no echo
pntfls4:popf
pop dx
pop cx
pop bx
pop ax
jnc pntflsx ; nc = success
call pntchk ; c = error (printer not ready)
pntflsx:ret
pntflsh endp
; Check for PRN (DOS's printer) being ready. If ready, return with C clear
; Otherwise, write Not Ready msg on mode line and return with C bit set.
; N.B. DOS Critical Error will occur here if PRN is not ready. [jrd]
pntchk proc near
push dx
push cx
push ax
mov cx,10 ; ten retries before declaring error
pntchk0:mov ah,ioctl ; get printer status, via DOS
mov al,7 ; status for output
push bx
mov bx,4 ; std handle for DOS system printer
int dos
pop bx
jc pntchk1 ; c = call failed
cmp al,0ffh ; code for Ready?
je pntchk3 ; e = yes, assume printer is ready
pntchk1:push cx ; save counter, just in case
mov ax,100 ; wait 100 millisec
call pcwait
pop cx
loop pntchk0 ; and try a few more times
; get here when printer is not ready
test yflags,modoff ; is mode line off?
jnz pntchk2 ; nz = off, skip msg
push bx
push si
mov si,offset pntmsg ; say printer not ready
mov cx,pntmsgl ; length
call modwrt ; write alternate mode line
pop si
pop bx
pntchk2:pop ax
pop cx
pop dx
stc ; say printer not ready
ret
pntchk3:pop ax
pop cx
pop dx
clc ; say printer is ready
ret
pntchk endp
;;;;; General screen management routines for IBM PC
; computes screen location to ax, given row and col in [dh,dl], resp.
scrloc proc near
mov al,dh ; get row
mul crt_cols ; multiply by number of columns
add al,dl ; plus current column number
adc ah,0 ; ripple carry
shl ax,1 ; double for attributes
ret
scrloc endp
; Routine to set cursor type. Pass cursor type in al: 0 = No cursor,
; 1 = Underline cursor, 2 = Block cursor. All cursors blink due to hardware.
; Routine frags any ac that video ints frag.
; For EGA boards running in non-25 line mode the cursor emulation is turned
; off during cursor shape changing and restored afterward. It's another
; ega Feature. [jrd]
; Sense crt_mode 18h as Tseng Labs UltraPAK mono board in 132 column mode.
csrtype proc near
push cx ; save the reg
mov ah,1 ; Video fxn for set cursor type
mov cx,0F00H ; Assume no cursor
cmp al,0 ; No cursor?
je csrty2 ; Right - set it and be done with it
cmp crt_mode,7 ; B&W card?
je csrty3 ; Yes - different sizes
cmp crt_mode,18h ; Tseng UltraPAK mono board?
je csrty3 ; e = yes, use mono cursor
mov cx,0607H ; No, use CGA underline cursor
cmp al,2 ; Block?
jne csrty2 ; No - set it now
csrty1: xor ch,ch ; Yes - make it a block
csrty2: cmp ega_mode,0 ; ega board active?
je csrty4 ; e = no
cmp byte ptr low_rgt+1,23 ; standard screen length?
je csrty4 ; e = yes, use regular cursor setting
push es ; EGA. turn off cursor emulation
mov ax,40h ; 40:87h is ega Info byte
mov es,ax
push es:[87h] ; save Info byte around call
or byte ptr es:[87h],1 ; set emulation off (low bit = 1)
mov ah,1 ; Video fxn for set cursor type
int screen
pop es:[87h] ; restore Info byte
pop es ; and our work register
pop cx
ret
csrty4: int screen ; regular cursor shape setting
pop cx
ret
csrty3: mov cx,0B0CH ; Assume B&W underline cursor
cmp al,2 ; Block?
jne csrty2 ; No - set it now
jmp csrty1 ; Yes - make it a block
csrtype endp
; Save the entire screen in a buffer so we can restore and/or dump it.
; Saves regular (80x25) screens to memory buffer scrsav and other sized
; screens to video memory page 1. Resultant save place put into savadr
; (offset then segment) and current low_rgt size info in savflg. Note,
; some Environments (TopView/Windows etc) may not permit use of page 1. [jrd]
savescr proc near
push es
push ds
push ax
push cx
push si
push di
call scrseg ; get screen segment in ax and es:di
push ax ; save screen segment
mov si,0
mov di,scrsav ; place to put screen (memory buff)
mov savadr+2,di ; working seg address for restore
mov savadr,0 ; and no offset for memory buffer
call scrmod ; ascertain video mode and screen
mov ax,low_rgt ; text screen lower right (typ 23,79)
mov savflg,ax ; save it for screen restore
inc al ; number of columns
add ah,2 ; plus status line = number of rows
cmp al,swidth ; same as preset screen space (80)?
ja savsc1 ; a = no, use screen video page 1
cmp ah,slen+1 ; same as preset screen length (24)?
je savsc3 ; e = yes, use our memory buffer
savsc1: mul ah ; times rows = characters on screen
shl ax,1 ; times two for attributes = page 1
mov cx,ax ; cx = working copy of screen size
and cx,000fh ; get lower four bits for offset part
mov savadr,cx ; save offset in this word
mov cl,4
shr ax,cl ; compute number of paragraphs
pop di ; source screen address
push di ; restore again
add di,ax ; add paragraphs, point di to page 1
mov savadr+2,di ; and save segment in this word
savsc3:
mov es,savadr+2 ; segment of storage area
mov di,savadr ; offset of same
mov ax,low_rgt ; lower right of text screen
inc al ; number of columns on screen
add ah,2 ; number of rows on screen
mul ah ; number of characters on the screen
mov cx,ax ; save this in counter cx
call scroff ; turn off screen [dt]
pop ds ; address screen
cld
rep movsw ; save the screen
pop di
pop si
pop cx
pop ax
pop ds ; restore this
call scron ; turn on screen [dt]
pop es
ret
savescr endp
; restore screen from buffer (offset and seg in savadr, text coord in savflg).
; Restores all screen lines. [jrd]
restscr proc near
push es
mov ax,savflg ; saved low_rgt text screen coord
add ah,2 ; number of screen lines
inc al ; number of screen columns
mul ah ; columns time lines = # characters
mov cx,ax ; save this in counter cx
push cx ; save count
call scrseg ; get address of screen in es:di
call scroff ; turn off screen [dt]
push ds ; save original data segment
mov si,savadr ; offset of storage area
push savadr+2 ; segment of same
pop ds ; put storage segment into ds
cld
rep movsw ; restore data to screen
pop ds ; recover original data segment
call scron ; turn on screen [dt]
pop cx ; recover count
call scrsync ; synch Topview with new screen
pop es
ret
restscr endp
; Save the screen to a buffer and then append buffer to a disk file. [jrd]
; Default filename is Kermit.scn; actual file can be a device too. Filename
; is determined by mssset and is passed as pointer dmpname.
; Dumpscr reads the screen image saved by savescr so call savescr call first.
dumpscr proc near
push ax
push bx
push cx
push dx
mov dmphand,-1 ; preset illegal handle
mov dx,offset dmpname ; name of disk file, from mssset
mov ax,dx ; where isfile wants name ptr
call isfile ; what kind of file is this?
jc dmp5 ; c = no such file, create it
test byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
jnz dmp0 ; nz = no.
mov al,1 ; writing
mov ah,open2 ; open existing file
int dos
jc dmp0 ; c = failure
mov dmphand,ax ; save file handle
mov bx,ax ; need handle here
mov cx,0ffffh ; setup file pointer
mov dx,-1 ; and offset
mov al,2 ; move to eof minus one byte
mov ah,lseek ; seek the end
int dos
jmp dmp1
dmp5: test filtst.fstat,80h ; access problem?
jnz dmp0 ; nz = yes
mov ah,creat2 ; file did not exist
mov cx,20h ; attributes, archive bit
int dos
mov dmphand,ax ; save file handle
jnc dmp1 ; nc = ok
dmp0: mov ah,3 ; get cursor position
xor bx,bx ; page 0
int screen
push dx ; save it
mov dh,byte ptr low_rgt+1 ; go to status line
inc dh
xor dl,dl ; left most column
mov ah,2 ; position cursor
int screen
mov dx,offset dmperr ; say no can do
mov ah,prstr
int dos
pop dx ; get original cursor position
mov ah,2 ; position cursor
xor bx,bx ; page 0
int screen
pop dx
pop cx
pop bx
pop ax
clc
ret
dmp1: mov ah,ioctl ; is destination ready for output?
mov al,7 ; test output status
mov bx,dmphand ; handle
int dos
jc dmp0 ; c = error
cmp al,0ffh ; ready?
jne dmp0 ; ne = not ready
push di ; read screen buffer, write lines
push si
push es
mov cl,byte ptr low_rgt+1 ; number of lines - 2
add cl,2 ; number of line on screen
xor ch,ch
mov si,savadr ; offset in storage area
dmp2: push cx ; save outer loop counter
mov es,savadr+2 ; get storage segment
mov di,offset dumpbuf ; data segment memory
mov cl,byte ptr savflg ; number of columns on screen - 1
inc cl ; number of columns on screen
xor ch,ch
dmp3: mov ax,word ptr es:[si] ; read char + attribute
mov byte ptr [di],al ; store just char, don't use es:
inc si ; update pointers
inc si
inc di
loop dmp3 ; do for each column
std ; set scan backward
mov cl,byte ptr savflg ; number of columns on screen - 1
inc cl ; number of columns on screen
xor ch,ch
push es
mov ax,ds
mov es,ax ; set es to data segment for es:di
mov di,offset dumpbuf ; start of line
add di,cx ; plus length of line
dec di ; minus 1 equals end of line
mov al,' ' ; thing to scan over
repe scasb ; scan until non-space
cld ; set direction forward
pop es
jz dmp3a ; z = all spaces
inc cx
inc di
dmp3a: mov word ptr [di+1],0A0Dh ; append cr/lf
add cx,2 ; line count + cr/lf
mov dx,offset dumpbuf ; array to be written
mov bx,dmphand ; need file handle
mov ah,write2 ; write the line
int dos
pop cx ; get line counter again
jc dmp3b ; c = error
loop dmp2 ; do next line
mov dx,offset dumpsep ; put in formfeed/cr/lf
mov cx,3 ; three bytes overall
mov ah,write2 ; write them
dmp3b: mov bx,dmphand ; file handle
int dos
mov ah,close2 ; close the file now
int dos
dmp6: pop es
pop si
pop di
pop dx
pop cx
pop bx
pop ax
clc
ret
dumpscr endp
; Get CRT mode - returns mode in variable crt_mode,
; updates crt_cols and low_rgt.
; For EGA active it looks in Bios work memory 40:84H for number of rows. [jrd]
scrmod proc near
push ax
push dx
mov ah,15 ; Get current video state
int screen
mov crt_mode,al ; Store CRT mode value
mov crt_cols,ah ; store # of cols
mov dl,ah ; # of cols again
mov dh,crt_lins ; and # of rows (constant from msster)
cmp ega_mode,0 ; ega active?
je scrmod4 ; e = no
push es ; yes, permit different lengths
mov ax,40h ; refer to 40:84h for # ega rows
mov es,ax
mov ah,es:[84h] ; get number of rows - 1 (typ 24)
cmp ah,20 ; less than 20 rows?
jb scrmod3 ; b = yes, ignore this length
cmp ah,80 ; more than 80 rows?
ja scrmod3 ; a = yes, ignore this length
mov dh,ah ; use this length
mov crt_lins,dh ; update our working constant
scrmod3:pop es
scrmod4:dec dl ; max text column, count from zero
dec dh ; max text row, count from zero
mov low_rgt,dx ; save away window address
pop dx
pop ax
ret
scrmod endp
; Get screen segment - returns screen segment in ax, and full address in es:di
scrseg proc near
xor di,di ; start at beginning of screen (0,0)
mov ax,0B000H ; Assume B&W card
cmp crt_mode,7 ; Is it?
je scrse1 ; e = yes
cmp crt_mode,18h ; Tseng UltraPAK mono in 132 col?
je scrse1 ; e = yes, use seg B000H
mov ax,0B800H ; No - video memory is here on color
cmp crt_mode,12 ; graphics set?
jb scrse1 ; b = no
cmp crt_mode,18 ; end of ordinary 640x480 graphics
ja scrse1 ; a = no, assume CGA segment
mov ax,0A000H ; graphics
scrse1: mov es,ax ; tell Topview our hardware address needs
mov tv_segs,es ; save our hardware screen address
mov tv_sego,di ; segment and offset form
mov tv_mode,1 ; assume we're running under Topview
mov ah,tvhere ; query Topview for its presence
int screen
mov ax,es ; get its new segment for screen work
cmp ax,tv_segs ; same as hardware?
jne scrse2 ; ne = no, we are being mapped
cmp di,tv_sego ; check this too
jne scrse2 ; ne = no too. Use TV's work buf as screen
mov tv_mode,0 ; else no Topview or no mapping
scrse2: mov tv_segs,es ; save segment
mov tv_sego,di ; and offset
ret
scrseg endp
; Synchronize a Topview provided virtual screen buffer with the image
; seen by the user. Requires cx = number of words written to screen
; (char & attribute bytes) and es:di = ENDING address of screen write.
; Changes ax and di.
scrsync proc near
cmp tv_mode,0 ; Topview mode active?
je scrsyn1 ; e = no, skip DOS call below
sub di,cx ; backup to start byte (cx = words)
sub di,cx ; after storing words to screen
mov ah,tvsynch ; tell Topview we have changed screen
int screen ; so user sees updated screen
scrsyn1:ret
scrsync endp
; The following two routines are used to turn off the display while we
; are reading or writing the screen in one of the color card modes.
; Turn screen off for (known) color card modes only. All regs preserved.
; Includes code for old procedure scrwait. 16 June 1987 [jrd]
scroff proc near
cmp refresh,0 ; slow refresh?
jne scrofx ; ne = no wait
cmp ega_mode,0 ; Extended Graphics Adapter in use?
jne scrofx ; ne = yes, no waiting
cmp tv_mode,0 ; Topview mode?
jne scrofx ; ne = yes, no waiting
cmp crt_mode,7 ; B&W card?
jnb scrofx ; Yes - just return
push ax ; Save ax and dx
push dx
mov dx,crt_status ; CGA: Wait for vertical retrace
scrof1: in al,dx
test al,disp_enb ; display enabled?
jnz scrof1 ; yes, keep waiting
scrof2: in al,dx
test al,disp_enb ; now wait for it to go off
jz scrof2 ; so can have whole cycle
mov dx,crtmset ; Output to CRT mode set port
mov al,25H ; This shuts down the display
out dx,al ; Dumb, but card is too
pop dx ; restore regs
pop ax
scrofx: ret
scroff endp
; Turn screen on for (known) color card modes only
; All registers are preserved.
scron proc near
cmp refresh,0 ; slow refresh?
jne scronx ; ne = no wait
cmp ega_mode,0 ; Extended Graphics Adapter in use?
jne scronx ; ne = yes, no waiting
cmp tv_mode,0 ; Topview mode?
jne scronx ; ne = yes, no waiting
cmp crt_mode,7 ; B&W card?
jnb scronx ; Yes - just return
push ax ; Save ax, dx, and si
push dx
push si
mov al,crt_mode ; Convert crt_mode to a word
xor ah,ah
mov si,ax ; Get it in a usable register
mov al,msets[si] ; Fetch the modeset byte
mov dx,crtmset ; This port
out dx,al ; Flash it back on
pop si ; restore regs
pop dx
pop ax
scronx: ret
scron endp
; Screen clearing routine. [IU]
;
; Call: ax/ coordinates of first screen location to be cleared.
; bx/ coordinates of last location to be cleared.
; Coord: ah = row [0-24], al = column [0-79]. Preserves all registers. [jrd]
atsclr: push ax ; save regs
push cx
push dx
mov dx,bx ; Compute last screen offset in ax
push ax
call scrmod ; update column length
pop ax ; scrmod zaps ax
push ax
call scrloc ; get screen start address in ax
mov cx,ax ; Save it in cx for a minute
pop dx ; Compute first screen offset in ax
call scrloc
sub cx,ax ; Compute number of locs to clear
add cx,2
sar cx,1 ; Make byte count a word count
jle atscl2 ; If nothing to clear, then vamos
push di ; save regs
push es ; save es
push ax ; save around call
call scrseg ; Get address of screen in ax, es:di
pop ax ; recover displacement
add di,ax ; displacement memory address
mov ah,scbattr ; Use current screen background attr
mov al,' ' ; Use space for fill
mov dl,byte ptr low_rgt ; line length - 1
inc dl ; line length
xor dh,dh
;;;;; cmp cx,dx ; Blanking a line or less??
;;;;; jg atscl1 ; No - make scroff disable display
atscl1: call scroff ; Turn screen off if color card
push cx ; save word count for Topview
cld
rep stosw ; Blit... (excuse PDP-10ese please)
pop cx ; recover word count
call scrsync ; synch Topview
call scron ; Turn screen back on if color card
pop es ; Restore segment register
pop di ; And destination index
atscl2: pop dx ; restore regs
pop cx
pop ax
ret
; Scrolling routines. vtscru scrolls up, vtscrd scrolls down 'scroll'
; rows. The top line is saved in the circular buffer before scrolling up.
; When running under an Environment control number of line positions moved
; to be less than scrolling region. [jrd]
; All registers are preserved.
; Screen-roll down. Move text down one line, for terminal emulator only.
vtscrd: push ax ; Upgraded by [jrd]
push bx
push cx
push dx
mov ah,7 ; scroll down
mov ch,mar_top ; top margin line
mov cl,0 ; left most column
mov dh,mar_bot ; bottom margin line
mov dl,byte ptr low_rgt ; right most column
mov bh,scbattr ; attributes
mov bl,dh
sub bl,ch ; region size - 1 line
mov al,scroll ; number of lines to scroll, from msz
vscrd1: cmp al,bl ; want to scroll more that than?
jbe vscrd2 ; be = no
push ax
mov al,bl ; limit to region-1 for Windows
int screen ; and do in parts
pop ax
sub al,bl ; get remainder
jmp short vscrd1 ; do next part
vscrd2: int screen ; scroll it down
pop dx
pop cx
pop bx
pop ax
ret
; Screen scroll up one line (text moves up) for terminal emulator use.
; When running under an Environment control number of line positions moved
; to be less than scrolling region. [jrd]
vtscru: push ax ; Upgraded by [jrd]
push bx
push cx
push dx
mov cl,scroll ; number of lines to scroll
mov ch,0
jcxz vscru3 ; z = nothing to do
cmp mar_top,0 ; scrolling the top screen line?
ja vscru2 ; a = no. don't save anything
push si
push di
call scroff ; turn off color screen
mov si,tv_sego ; screen offset for es:si
mov bx,offset twnd ; put lines in top window buffer
vscru1: push cx ; save count
call putcirc ; put screen line in circular buffer
pop cx
loop vscru1 ; save 'scroll' number of lines
call scron ; turn on screen again
pop di
pop si ; now scroll the visible screen
vscru2: mov ah,6 ; scroll up
mov dh,mar_bot ; bottom row
mov dl,byte ptr low_rgt ; right most column
mov ch,mar_top ; top row of scrolling region
mov cl,0 ; left most column
mov bh,scbattr ; attributes
mov bl,dh
sub bl,ch ; region size - 1 line
mov al,scroll ; number of lines to scroll, from msz
vscru2a:cmp al,bl ; want to scroll more that than?
jbe vscru2b ; be = no
push ax
mov al,bl ; limit to region - 1 for Windows
int screen ; and do in parts
pop ax
sub al,bl
jmp short vscru2a ; do next part
vscru2b:int screen ; scroll up that region
vscru3: pop dx ; Restore the rest of the regs
pop cx
pop bx
pop ax
ret
;screen text roll up, version for manual scrolling only
mscru: push ax ; Upgraded by [jrd]
push bx
push cx
push dx
push si
push di
cmp bwnd.lcnt,0 ; any lines in bottom window?
je mscru2 ; e = no, so ignore request
call scroff ; turn off color screen
mov bx,offset twnd ; this is where it goes
mov si,tv_sego ; screen offset for es:si
call putcirc ; put screen line in circular buffer
mov ax,601H ; scroll up one line
mov dx,low_rgt ; lower right corner
xor cx,cx ; top row of scrolling region
mov bh,scbattr ; background attributes
int screen ; scroll up that region
mov dx,low_rgt
mov dl,0 ; location is lower left corner
call scrloc ; get count from display start
mov di,ax
push es
mov bx,tv_segs ; get screen's segment into, es:di
mov es,bx ; segment
add di,tv_sego ; destination memory address (es:di)
mov bx,offset bwnd ; source of lines
call getcirc ; get line from circ buf to screen
pop es ; restore es
call scron ; turn on the screen
mscru2: pop di ; Restore the rest of the regs
pop si
pop dx
pop cx
pop bx
pop ax
ret
;screen text scroll down, for manual mode only
mscrd: push ax ; Upgraded by [jrd]
push bx
push cx
push dx
push si
push di
cmp twnd.lcnt,0 ; any lines left in top window?
je mscrd1 ; e = no, ingore request
call scroff ; turn off screen
mov dx,low_rgt ; from screen location, row
mov dl,0 ; starting in col 0
call scrloc ; get offset in display buffer in ax
mov si,tv_sego ; screen offset for es:di
add si,ax ; source addr in display buffer es:si
mov bx,offset bwnd ; buffer to use (bottom window)
call putcirc ; copy bottom screen line to circ buf
mov ax,701H ; scroll down one line
xor cx,cx ; top left corner
mov dx,low_rgt ; bottom right corner
mov bh,scbattr ; attributes
int screen ; scroll it down
push es
mov di,tv_segs ; screen segment
mov es,di
mov di,tv_sego ; screen offset, for es:di
mov bx,offset twnd ; buffer to use (top window)
call getcirc ; copy from circ buf to screen
pop es
call scron ; turn on display again
mscrd1: pop di ; Restore the rest of the regs
pop si
pop dx
pop cx
pop bx
pop ax
ret
; move viewing window down as much as possible (text moves up)
endwnd proc near ; go to end of scrolling text
push cx
mov cx,bwnd.lcnt ; all bottom window lines [dlk]
jmp dnwp0 ; and enter dwnpg
endwnd endp
dnone proc near ; move text up one line [jrd]
push cx
mov cx,1
jmp dnwp0
dnone endp
; scroll viewing window down (text moves up) one page (24 lines)
dnwpg proc near
push cx
mov cl,byte ptr low_rgt+1 ; number of rows, excl status
inc cl ; count from 1, not 0
mov ch,0
dnwp0: ; additional entry point
cmp bwnd.lcnt,cx ; enough lines in bottom line buffer?
jge dnwp1 ; ge = we have that many lines stored
mov cx,bwnd.lcnt ; do as many as we have
dnwp1: jcxz dnwp2 ; z = nothing to do
cmp tekflg,0 ; Tek mode active?
jne dnwp2 ; ne = yes, no scrolling
call mscru ; scroll up text one line
loop dnwp1
dnwp2: pop cx
clc
ret
dnwpg endp
; home viewing window
homwnd proc near
push cx
mov cx,twnd.lcnt ; all top window lines [dlk]
jmp upwp0 ; join upwpg
homwnd endp
upone proc near ; move text down one line [jrd]
push cx
mov cx,1
jmp upwp0
upone endp
; scroll viewing window up (text moves down) a page (24 lines)
upwpg proc near
push cx
mov cl,byte ptr low_rgt+1 ; number of rows, excl status line
inc cl ; count from 1, not 0
mov ch,0
upwp0: ; additional entry point
cmp twnd.lcnt,cx ; enough lines in top line buffer?
jae upwp1 ; ae = at least as many as requested
mov cx,twnd.lcnt ; do only as many as are stored
upwp1: jcxz upwp2 ; z = no lines to scroll
cmp tekflg,0 ; Tek mode active?
jne upwp2 ; ne = yes, no scrolling
call mscrd ; roll down text one line
loop upwp1
upwp2: pop cx
clc
ret
upwpg endp
; Put a line into the circular buffer. Pass the buffer structure in bx.
; Source is tv_segs:si which is the current screen address.
; Rewritten by [jrd]
putcirc proc near
push es
mov cl,crt_cols ; number of columns
xor ch,ch
mov es,[bx].orig ; get segment of memory area
cmp bx,offset bwnd ; bottom buffer?
je putci6 ; e = yes
mov di,twnd.pp ; pick up buffer ptr (offset from es)
add di,cx ; increment to next available slot
add di,cx ; char and attribute
cmp di,twnd.bend ; would line extend beyond buffer?
jb putci1 ; b = not beyond end
mov di,0 ; else start at the beginning
putci1: mov twnd.pp,di ; update ptr
cld ; set direction to forward
push ds ; save regular datas seg reg
mov ds,tv_segs ; use screen segment for ds:si
rep movsw ; copy into buffer
pop ds ; restore regular datas segment
mov cx,twnd.lmax ; line capacity of buffer
dec cx ; minus one work space line
cmp twnd.lcnt,cx ; can we increment line count?
jae putci1b ; ae = no, keep going
inc twnd.lcnt ; else count this line
putci1b:cmp bwnd.lcnt,0 ; any lines in bottom buffer?
je putci2 ; e = no
mov cx,bwnd.pp ; see if we overlap bot buf
cmp cx,twnd.pp ; is this line in bot buf area?
jne putci2 ; ne = no
add cl,crt_cols ; move bottom pointer one slot earlier
adc ch,0
add cl,crt_cols ; words
adc ch,0
cmp cx,bwnd.bend ; beyond end of buffer?
jb putci1a ; b = no
mov cx,0 ; yes, start at beginning of buffer
putci1a:mov bwnd.pp,cx ; new bottom pointer
dec bwnd.lcnt ; one less line in bottom buffer
putci2: pop es
ret
putci6: ; bottom buffer
add cx,cx ; words worth
cmp bwnd.lcnt,0 ; any lines in the buffer yet?
jne putci7 ; ne = yes
mov di,twnd.pp ; get latest used slot of top buff
add di,cx ; where first free (?) slot starts
cmp di,bwnd.bend ; are we now beyond the buffer?
jb putci6a ; b = no
mov di,0 ; yes, start at beginning of buffer
putci6a:add di,cx ; start of second free (?) slot
cmp di,bwnd.bend ; are we now beyond the buffer?
jb putci6b ; b = no
mov di,0 ; yes, start at beginning of buffer
putci6b:mov cx,twnd.lmax ; buffer line capacity
sub cx,twnd.lcnt ; minus number used by top buffer
sub cx,2 ; minus one work slot and one we need
cmp cx,0 ; overused some slots?
jge putci8 ; ge = enough to share
add twnd.lcnt,cx ; steal these from top window beginning
jmp short putci8
putci7: mov es,bwnd.orig ; get segment of memory area
mov di,bwnd.pp ; pick up buffer ptr (offset from es)
cmp di,0 ; would line start before buffer?
jne putci7a ; ne = after start of buffer
mov di,bwnd.bend ; else start at the end minus one slot
inc di
putci7a:sub di,cx
putci8: mov bwnd.pp,di ; update ptr (this is latest used slot)
mov cl,crt_cols
xor ch,ch
cld ; set direction to forward
push ds ; save regular datas seg reg
mov ds,tv_segs ; use screen segment for ds:si
rep movsw ; copy into buffer
pop ds ; restore regular datas segment
mov cx,bwnd.lmax ; line capacity of buffer
cmp bwnd.lcnt,cx ; can we increment line count?
jae putci8b ; ae = no, keep going
inc bwnd.lcnt ; else count this line
putci8b:cmp twnd.lcnt,0 ; any lines in top line buf?
je putci9 ; e = no
mov cx,twnd.pp ; yes, see if we used last top line
cmp cx,bwnd.pp ; where we just wrote
jne putci9 ; not same place, so all is well
dec twnd.lcnt ; one less line in top window
cmp cx,0 ; currently at start of buffer?
jne putci8a ; ne = no
mov cx,twnd.bend ; yes
inc cx
putci8a:sub cl,crt_cols ; back up top window
sbb ch,0
sub cl,crt_cols ; by one line
sbb ch,0
mov twnd.pp,cx ; next place to read
putci9: pop es
ret
putcirc endp
; Get a line from the circular buffer, removing it from the buffer.
; returns with carry on if the buffer is empty.
; Pass the buffer structure in bx.
; Destination preset in es:di which is the current screen address.
; Rewritten by [jrd]
getcirc proc near
cmp [bx].lcnt,0 ; any lines in buffer?
jne getci1 ; ne = yes, ok to take one out
stc ; else set carry
ret
getci1: ; top and bottom window common code
mov cl,crt_cols ; # of chars to copy
xor ch,ch
mov si,[bx].pp ; this is source
push si ; save around calls
push cx ; save around calls
cld ; set direction to forward
push ds ; save original ds
mov ax,[bx].orig ; use seg address of buffer for si
mov ds,ax
rep movsw ; destination = screen at es:di
pop ds ; recover original data segment
pop cx ; recover word count
call scrsync ; synch Topview
pop si ; get ptr again
add cx,cx ; words
cmp bx,offset bwnd ; bottom window?
je getci7 ; e = yes
sub si,cx ; top window, move back
jnc getci6 ; nc = still in buffer, continue
mov si,twnd.bend ; else use end of buffer
sub si,cx ; minus length of a piece
inc si
getci6: mov twnd.pp,si ; update ptr
dec twnd.lcnt ; decrement # of lines in buffer
clc ; make sure no carry
ret
getci7: ; bottom window
add si,cx ; words, move back (bot buf = reverse)
cmp si,bwnd.bend ; still in buffer?
jb getci8 ; b = yes
mov si,0 ; else use beginning of buffer
getci8: mov bwnd.pp,si ; update ptr
dec bwnd.lcnt ; decrement # of lines in buffer
clc ; make sure no carry
ret
getcirc endp
;
; CHKDSP - procedure to check for hardware support of 132 cols [dlk]
;
; Supported hardware: EVA board from Tseng Labs w/132-col kit installed
; Tseng Labs UltraPAK mono/Herc board w/132 column modes.
; Video 7 Vega Deluxe w/ 132X25.COM driver installed [tmk]
; and VGA board, ATI EGA Wonder, Everex ev-659 and fvga-673.
; The routine checks for the presence of a 132-column-capable adapter. If
; one is found, its handler returns the proper video mode in [CX]. The main-
; line code then moves this to [AX] and issues the video interrupt.
;
chgdsp proc near
push es ; save all we use
push ax
push bx
push cx
push dx
push si
push di
mov temp,ax ; save set/reset flag from msz
mov ah,flowoff ; get xoff
cmp ah,0 ; flow control?
je chgds0 ; e = none
call outchr ; send it
nop ; avoid serial port interrupts while
nop ; doing many rep scasb's below
nop
call savescr ; save current screen
mov ax,40 ; wait 40 millisec before video tests
call pcwait ; so don't mix screen and port intrpts
chgds0: call ckteva ; try Tseng Labs EVA
jnc chgds1 ; nc = found
call ckv7vd ; try Video 7 EGA Deluxe and VGA
jnc chgds1 ; nc = found
call ckatiw ; try ATI EGA Wonder
jnc chgds1 ; nc = found
call ckevrx ; try Everex Micro Enhancer Deluxe
jnc chgds1 ; nc = found
call ckevga ; try Everex EVGA-673
jnc chgds1 ; nc = found
jmp chgdsx ; if not, exit
; Perform mode change
chgds1: mov ax,cx ; get returned value in proper reg
int screen ; call the bios
cmp flags.modflg,1 ; is mode line enabled?
jbe chgds2 ; be = yes, and off or locally owned
mov flags.modflg,1 ; remove foreign ownership
chgds2: call scrini ; reset parameters
chgdsx: mov ah,flowon ; get flowon byte
cmp ah,0 ; using flow control?
je chgdsx1 ; e = no
call outchr ; send it
nop
nop
nop
chgdsx1:pop di ; restore what we saved
pop si
pop dx
pop cx
pop bx
pop ax
pop es
ret ; return to caller
chgdsp endp
; Individual tests for various 132-column boards
;
; Tseng LABS EVA and UltraPAK
ckteva: mov ax,0c000h ; seg addr for EVA
mov es,ax ; set into es register
mov di,76h ; offset of board's string
lea si,tsngid ; validation string
mov cx,tsnglen ; length of validiation string
cld
repe cmpsb ; compare strings
je ckteva2 ; e = strings match
mov ax,4d00h ; check for UltraPAK mono driver
int screen
cmp ax,5aa5h ; driver signature?
jne chnoad ; ne = no
mov cx,7 ; default to mono (7) for this board
cmp byte ptr temp,0 ; setting 132 columns?
je ckteva1 ; e = resetting to normal
mov cx,18h ; set to 132 cols (Set Mode 18H)
ckteva1:clc ; carry clear means found
ret
ckteva2: ; an EVA board - check for 132 col kit
cmp byte ptr es:099h,0 ; check 132 col kit installed
je chnoad ; e=0=not installed
jmp catfnd ; do the mode change
chnoad: stc ; indicate adapter not present
ret ; and exit
;
; ATI EGA Wonder
ckatiw: mov ax,0c000h ; seg addr for EGA Wonder
mov es,ax ; set into es register
mov di,012fh ; offset of message in ROM
lea si,atiwid ; offset of message here
mov cx,atilen ; length of validation string
cld
repe cmpsb ; compare strings
jne chnoad ; ne = strings differ
;
catfnd: mov cx,0003h ; prepare to reset video mode
cmp byte ptr temp,0 ; are we setting or resetting?
je ckexit ; e is reset, exit
mov cx,0023h ; set to 132 cols (Set Mode 23H)
ckexit: clc ; carry clear means found
ret
;
; Video 7 Vega Deluxe
ckv7vd: mov ax,0c000h ; seg addr for Vega rom bios
mov es,ax ; set into es register
mov di,002ah ; offset of message in ROM
lea si,vid7id ; offset of message here
mov cx,vid7len
cld
repe cmpsb ; compare strings
je cnv7fn0 ; e = same
mov di,002ah ; offset of ident string
mov si,offset vid7id2 ; Video 7 VGA board
mov cx,vid7len2
repe cmpsb
je cnv7fn2 ; e = found
cnv7fx: jmp chnoad ; ne = strings are different
;
cnv7fn0:test byte ptr es:[03ffeh],1 ; is this a 'Deluxe' Vega?
jz chnoad ; z = nope, can't do it
mov ah,35h ; DOS Get Vector
mov al,10h ; Bios video interrupt
int dos ; get it into es:bx
mov di,bx ; es:bx is returned int 10h entry pnt
sub di,5ah ; back offset to msg in 132X25.COM
lea si,vid7id ; offset of validation message
mov cx,vid7len ; length of validation string
cld
cnv7fn1:repe cmpsb ; Look for repeat of msg by 132X25.COM
jne cnv7fn2 ; if different
mov cl,crt_mode ; prepare to reset video mode
mov ch,0
cmp byte ptr temp,0 ; are we setting or resetting?
je ckexit ; e is reset, exit
mov cx,0000h ; set to 132 cols (old 40x25)
jmp short ckexit ; and exit
cnv7fn2:mov ax,6f00h ; check for VegaBios driver
int screen
cmp bx,'V7' ; Video 7 Bios presence response
jne cnv7fx ; ne = not there
mov ax,6f01h ; al gets monitor type (mono,color,ega)
int screen
mov bx,51h ; presume mono 132x25, page 0
cmp crt_lins,42 ; 43 lines active?
jb cnv7fn2a ; b = no
inc bx ; use bx = 52h for 132x43
cnv7fn2a:
cmp al,10h ; analogue fixed freq (IBM 85xx)?
je cnv7fx ; e = yes, no 132 columns
cmp al,2 ; 1 = mono, 2 = color, above = ega
jb cnv7fn3 ; b = mono or unknown
mov bx,4fh ; presume med res color 132x25
je cnv7fn3 ; e = med res color, al = 2
mov bx,41h ; ega high res 132x25, enhanced mons
cmp crt_lins,42 ; 43 lines active?
jb cnv7fn3 ; b = no
inc bx ; use bx = 42h for 132x43
cnv7fn3:mov ax,6f05h ; set special mode found in bl
cmp byte ptr temp,0 ; resetting to 80 column mode?
jne cnv7fn4 ; ne = no, setting 132x25
mov al,crt_norm ; get normal mode
mov ah,0 ; set mode
cmp crt_lins,42 ; 43 lines active?
jb cnv7fn4 ; b = no
mov bl,40h ; use Video 7 mode 40h 80x43 for color
mov ax,6f05h ; and do special mode set
cnv7fn4:int screen ; special mode is in bl
mov cx,0f00h ; a nop screen bios command
clc
ret
ckevrx: mov ax,0c000h ; seg addr for Everex EV-659
mov es,ax ; set into es register
mov di,0047h ; offset of message in ROM
lea si,evrxid ; offset of message here
mov cx,evrxlen ; length of validation string
cld
repe cmpsb ; compare strings
jne ckfnr2 ; ne = strings differ
mov ah,crt_lins ; we recognize either 44 or 25 rows
cmp ah,43 ; equal to 44-1 rows?
jne ckfnr1 ; ne = no
mov cx,0070h ; Everex extended mode ident
mov bl,09h ; prepare to reset video mode to 80x44
cmp byte ptr temp,0 ; are we setting or resetting?
je ckfnr4 ; e is reset, exit
mov bl,0bh ; 132x44
jmp ckexit
ckfnr1: cmp ah,24 ; equal to 25-1 rows?
je ckfnr3 ; e = yes
ckfnr2: jmp chnoad ; ne = no
ckfnr3: mov cx,0003h ; prepare to reset video mode
cmp byte ptr temp,0 ; are we setting or resetting?
je ckfnr4 ; e is reset, exit
mov cx,0070h ; Everex extended mode ident
mov bl,0ah ; 132x25
ckfnr4: jmp ckexit
ckevga: mov ax,0c000h ; Everex FVGA-673, rom segment
mov es,ax
mov di,76h ; offset in rom for board's id string
lea si,evgid ; id string
mov cx,evglen ; length of id string
cld
repe cmpsb ; do they match?
jne ckevg2 ; ne = no
mov cx,3 ; prepare to reset video mode
cmp byte ptr temp,0 ; setting or resetting mode?
je ckevg1 ; e = resetting, exit
mov cx,0070h ; mode for 132x25
mov bl,0ah ; Everex mode 0ah
ckevg1: clc
ret
ckevg2: stc ; say board not found
ret
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr.
RSKP PROC NEAR
pop bp
add bp,3
push bp
ret
RSKP ENDP
; Jumping here is the same as a ret
R PROC NEAR
ret
R ENDP
code ends
if1
%out [End of pass 1]
else
%out [End of assembly]
endif
end